package com.gowants.pems.controller;

import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.apache.commons.lang.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.gowants.pems.model.ErrorCode;
import com.gowants.pems.model.SysPower;
import com.gowants.pems.model.SysUser;
import com.gowants.pems.service.ErrorCodeService;
import com.gowants.pems.service.SysPowerService;
import com.gowants.pems.service.SysUserService;
import com.gowants.pems.util.DateUtil;
import com.gowants.pems.util.DesUtil;
import com.gowants.pems.util.JSONList;
import com.gowants.pems.util.JSONMap;
import com.gowants.pems.util.RedisUtils;

/**
 * Controller基类
 * 
 * @author GJR
 *
 */
public class BaseController
{
	@Autowired
	private ErrorCodeService errorCodeService;
	@Autowired
	private SysPowerService sysPowerService;
	@Autowired
	private RedisUtils redisUtils;
	@Autowired
	//private ParamsMapper paramsMapper;
	private SysUserService sysUserService;
	
	/**
	 * 指定默认分页大小
	 */
	@Value("${gowants.pagesize}")
	public int pagesize;
	/**
	 * session 过期时间
	 */
	@Value("${spring.redis.shiro.expire}")
	private int expire;
	
	@Value("${gowants.redisKey}")
	private String redisKey;
	/**
	 * 
	 * <获取请求参数>
	 * @param requestData 请求参数JSON
	 * @return
	 * @remake create by GJR 2019年5月8日 上午9:54:12
	 */
	public JSONMap getRequestBody(String requestData) 
	{
	    return JSONMap.parseJSONMap(requestData);
	}
	
	/**
	 * 
	 * <获取list参数>
	 * @param requestData
	 * @return
	 * @remake create by GJR 2019年5月11日 下午4:01:06
	 */
	public JSONList getRequestForList(String requestData) 
	{
	    return JSONList.parseJSONList(requestData);
	}
	
	/**
	 * 
	 * <获取指定类型的请求参数>
	 * @param requestData 请求JSON参数
	 * @param clazz 指定范型
	 * @return
	 * @remake create by GJR 2019年5月8日 上午9:53:35
	 */
    public <T> T getRequestBody(String requestData, Class<T> clazz) 
    {
        JSONMap body = getRequestBody(requestData);
        
        return JSONMap.parseObject(body.toJSONString(), clazz);
    }
	
    /**
     * 
     * <获取指定类型的请求参数>
     * @param requestData
     * @param key
     * @param clazz
     * @return
     * @remake create by GJR 2019年5月8日 上午10:11:19
     */
    public <T> T getRequestBody(String requestData, String key, Class<T> clazz) 
    {
        JSONMap body = getRequestBody(requestData);
        
        return JSONMap.parseObject(body.getJSONMap(key).toJSONString(), clazz);
    }

	/**
	 *
	 * <请求相应信息>
	 * @param request http请求对象
	 * @param responseData 返回信息
	 * @return
	 * @remake create by GJR 2019/6/3 12:45
	 */
    public JSONMap doResponse(HttpServletRequest request, Object responseData)
	{
		// 响应信息
		JSONMap responseMap = new JSONMap();
		responseMap.put("resultData", responseData);
		return responseMap;
	}

	/**
	 * <无具体参数返回>
	 *
	 * @paam a
	 * @retrn a
	 * @remake create by GJR 2019/6/18 16:19
	 */
	public JSONMap doResponse(HttpServletRequest request, String code)
	{
		return doResponse(request, code, null);
	}

	/**
	 * 
	 * <请求相应信息>
	 * @param request http请求对象
	 * @param code 提示码
	 * @param responseData 返回信息
	 * @return
	 * @remake create by GJR 2019年4月26日 下午1:39:59
	 */
    public JSONMap doResponse(HttpServletRequest request, String code, Object responseData)
    {
        // 响应信息
        JSONMap responseMap = new JSONMap();
        // 获取请求渠道
        String channel = request.getHeader("isClient");
       
		// 是否客户端判断
     	if(isClient(request))
     	{
     		// 客户端逻辑
     		this.clientResult(responseMap, code, responseData, channel);
		}
     	else
		{
			// web端
			this.webResult(responseMap, code, responseData, channel);
		}

        return responseMap;
    }

	/**
	 * <客户端返回逻辑>
	 *
	 * @param
	 * @return
	 * @remake create by GJR 2019/6/19 17:23
	 */
    private void clientResult(JSONMap responseMap, String code, Object responseData, String channel)
	{
		if(null != responseData)
		{
			responseMap.put("resultData", responseData);
		}

		// code为空视为成功
		if("".equals(code))
		{
			responseMap.put("success", true);
			return;
		}

		// 查询提示信息对象
		ErrorCode errorCode = errorCodeService.getErrorCodeByChannel(code, channel);

		if(null == errorCode)
		{
			responseMap.put("success", false);
			responseMap.put("resultMsg", "提示码未定义, 请联系后台开发！");
			return;
		}

		responseMap.put("success", false);
		responseMap.put("resultMsg", errorCode.getValueZh());
	}

	/**
	 * <web端返回逻辑>
	 *
	 * @param
	 * @return
	 * @remake create by GJR 2019/6/19 17:23
	 */
	private void webResult(JSONMap responseMap, String code, Object responseData, String channel)
	{
		if(null == responseData)
		{
			responseData = new JSONMap();
		}
		// code为空视为成功，但不需要提示信息，只返回状态编码
		if("".equals(code))
		{
			responseMap.put("resultData", responseData);
			responseMap.put("status", 200);
			responseMap.put("isAlert", false);
			return;
		}

		// 查询提示信息对象
		ErrorCode errorCode = errorCodeService.getErrorCodeByChannel(code, channel);

		// 状态码未定义
		if(null == errorCode)
		{
			responseMap.put("status", 400);
			responseMap.put("icon", 5);
			responseMap.put("err_code", "");
			responseMap.put("isAlert", false);
//			responseMap.put("resultMsg", code);
			responseMap.put("resultMsg", "系统错误, 请联系统管理员！");
			return;
		}

		int status = errorCode.getStatusCode();
		int icon = errorCode.getIcon();
		String msg = errorCode.getValueZh();

		// 200为成功，但是需要页面有提示框
		if(status == 200)
		{
			responseMap.put("resultData", responseData);
		}
		if(status == 110||status == 119){
			responseMap.put("resultData", responseData);
		}

		responseMap.put("status", status);
		responseMap.put("icon", icon);
		responseMap.put("err_code", code);
		responseMap.put("isAlert", false);
		responseMap.put("resultMsg", msg);
	}

    /**
     * 
     * <获取当前登陆用户>
     * @return
     * @remake create by GJR 2019年4月28日 下午4:05:08
     */
    public SysUser getUser()
    {
    	
        return (SysUser) SecurityUtils.getSubject().getPrincipal();
    }

	/**
	 * 
	 * <获取用户ID>
	 * @return
	 * @remake create by TPH 2019年6月14日 上午9:12:37
	 */
	public String getUserId() 
	{
	    return getUser().getId();
	}

	/**
	 * <分页赋值>
	 *
	 * @param
	 * @return
	 * @remake create by GJR 2019/6/20 9:23
	 */
    public void pageSetData(HttpServletRequest req, JSONMap resultMap, int page, int limit, int totalPage, String hint, Object data, long total)
	{
		// 只有web返回状态和默认提示信息
		if(!isClient(req))
		{
			resultMap.put("status", 200);
			resultMap.put("hint", hint);
		}

		resultMap.put("page", page);
		resultMap.put("totalPage", totalPage);
		resultMap.put("limit", limit);
		resultMap.put("data", data);
		resultMap.put("total", total);
	}

	/**
	 * <分页赋值>
	 *
	 * @param
	 * @return
	 * @remake create by GJR 2019/6/20 9:23
	 */
	public void pageSetData(HttpServletRequest req, JSONMap resultMap, JSONMap requestData, List data)
	{
		// 只有web返回状态和默认提示信息
		if(!isClient(req))
		{
			resultMap.put("status", 200);
			resultMap.put("hint", requestData.getString("hint"));
		}

		PageHelper.startPage(requestData.getIntValue("page"),requestData.getIntValue("limit"));
		PageInfo pageInfo = new PageInfo(data);

		resultMap.put("page", requestData.getIntValue("page"));
		resultMap.put("totalPage", pageInfo.getPages());
		resultMap.put("limit", requestData.getIntValue("limit"));
		resultMap.put("data", data);
		resultMap.put("total", pageInfo.getTotal());

	}
	/**
	 * <是否客户端渠道判断>
	 *
	 * @param
	 * @return true 客户端; false web端
	 * @remake create by GJR 2019/6/19 17:58
	 */
    public boolean isClient(HttpServletRequest request)
	{
		// 获取请求渠道
		String channel = request.getHeader("isClient");
		// 返回数据类型标识(区分客户端和WEB端)
		String client = "1";//paramsMapper.getParamValueByNumber(Const.ISCLIENT);

		return client.indexOf(channel) != -1;
	}

    /**
     * 
     * <获取查询条件>
     * @param reqData 请求入参
     * @return json字符串集合
     * @remake create by GJR 2019年5月6日 上午11:34:23
     */
    public JSONList getCondition(String reqData)
    {
        JSONMap map = JSONMap.parseJSONMap(reqData);
		return map.getJSONList("condition");
    }

    
	/**
	 * <封装查询条件>
	 *
	 * @parm queryMap 查询条件返回Map， reqData 查询接口入参, 返回Bean类型
	 * @retun a
	 * @remake create by GJR 2019/7/9 9:24
	 */
	public <T> T buildQueryCondition(String reqData, Class<T> clazz) throws Exception
	{
		JSONList jsonCondition = getCondition(reqData);
		try
		{
			Object obj = clazz.newInstance();
	
			for(Object cond : jsonCondition)
			{
	
				JSONMap condition = JSONMap.parseJSONMap(cond.toString());
				Object keyword = condition.get("keyword");
	
				if("".equals(String.valueOf(keyword)))
				{
					continue;
				}
	
				String field = condition.getString("field");
				String fieldName = this.getFieldName(field);
				Field f = clazz.getDeclaredField(fieldName);
				f.setAccessible(true);
				f.set(obj, getFieldValue(f.getType(), keyword));
			}
	
			return (T)obj;
		}
		catch(InstantiationException e)
		{
			throw new Exception("TSMS_0000114");
		}
		catch(NoSuchFieldException e)
		{
			throw new Exception("TSMS_0000113");
		}
		catch(IllegalAccessException e)
		{
			throw new Exception("TSMS_0000113");
		}
		catch (IllegalArgumentException e)
		{
			throw new Exception("TSMS_0000112");
		}
	
	}

	/**
	 * <用户是否有某个权限>
	 *
	 * @param
	 * @return
	 * @remake create by GJR 2019/7/5 9:14
	 */
    public boolean hasPermission(String permission)
	{
		return SecurityUtils.getSubject().isPermitted(permission);
	}

	/**
	 * <用户是否有某些权限>
	 *
	 * @paam
	 * @retrn a
	 * @remake create by GJR 2019/7/5 9:20
	 */
	public boolean[] hasPermissionAsList(String... array)
	{
		return SecurityUtils.getSubject().isPermitted(array);
	}

	/**
	 * <获取对应类型字段值>
	 *
	 * @paam clz java.lang.String  , o "12321"
	 * @retrn a
	 * @remake create by GJR 2019/7/9 9:44
	 */
	private <T> T getFieldValue(Class<T> clz,Object o) throws InstantiationException, IllegalAccessException
	{

		if(clz.isInstance(o)){
			return clz.cast(o);
		}

		if(clz.equals(Integer.class))
		{
			return (T)Integer.valueOf(o.toString());
		}

		if(clz.equals(Date.class))
		{
			return (T)DateUtil.fomatDate(o.toString());
		}

		if(clz.equals(Float.class))
		{
			return (T)Float.valueOf(o.toString());
		}
//		Object obj = clz.newInstance();
//		if(obj instanceof java.util.Date)
//		{
//			return (T)DateUtil.fomatDate(o.toString());
//		}

		return null;
	}

	/**
	 * <获取字段名>
	 *
	 * @paam a
	 * @retrn a
	 * @remake create by GJR 2019/7/9 10:01
	 */
	private String getFieldName(String field)
	{

		if(field.indexOf("_") != -1)
		{
			return field.split("_")[0];
		}

		return field;
	}
	

	
	/**
	 * 验证没有登录的客户端请求是否正确
	 *
	 * @param
	 * @return 
	 * @remake 2019.8.1
	 */
    public boolean RequestValidation (HttpServletRequest request)
	{
    	try
    	{
		// 获取请求渠道
		String channel = request.getHeader("isClient");
		///验证是否为客户端
		
		String time = request.getHeader("time");
		
		String token = request.getHeader("RequestToken");
		
		if(!"client".equals(channel))
		{
			return false;
		}
		if("".equals(time))
		{
			return false;
		}
		if("".equals(token))
		{
			return false;
		}
		
		String decryptToken= DesUtil.decrypt(token,Charset.forName("UTF-8"), "tsms2019");
    	
		if("".equals(decryptToken))
		{
			return false;
		}
		String time1=time.substring(time.length()-4,time.length());
		time1=time1.subSequence(0, 2).toString();
		String result="";
		if(decryptToken.length()==11)
		{
			result = decryptToken.substring(decryptToken.length()-6,decryptToken.length());
			result="0"+result.subSequence(0, 1).toString();
			
			if(time1.equals(result))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		if(decryptToken.length()==12)
		{
			result = decryptToken.substring(decryptToken.length()-7,decryptToken.length());
			result=result.subSequence(0, 2).toString();
			if(time1.equals(result))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
    	
    	}
	 catch (Throwable e) {
		 return false;
    }
    	return false;
		
	}
	
    /**
     	* 验证是否有权限使用接口
     * @param url
     * @return
     */
    public boolean isPower (String url)
   	{
    	
    	try
    	{
    		//先取出缓存中是否存在
    		Object spObject=redisUtils.get(redisKey+"power:"+getUserId());
    		if(null!=spObject) {
	    		String sp= spObject.toString();
	    		if(StringUtils.isNotBlank(sp)) {
		    		List<SysPower> list = JSONObject.parseArray(sp, SysPower.class);
		     		for(SysPower sp0:list) {
		     			if(url.equals(sp0.getUrl())) {
		     				return true;
		     			}
		     		}
	    		}
    		}else {
    			//缓存中不存在证明缓存过期
    			SysPower record=new SysPower();
	    		record.setRoleId(getUser().getRole());
	    		record.setIsenable(1);
	    		List<SysPower> fp=sysPowerService.select(record);
				if(fp.size()>0) {
					for(SysPower sp:fp) {
						if(url.equals(sp.getUrl())) {
							redisUtils.set(redisKey+"power:"+getUser().getId(), JSON.toJSON(fp), expire);
		     				return true;
		     			}
					}
					redisUtils.set(redisKey+"power:"+getUser().getId(), JSON.toJSON(fp), expire);
				}
    			
    		}
    		
    		return false;
    	}
    	 catch (Exception e) {
    		 return false;
        }
    	
   	}
    /**
               * 验证tooken
     * @param request
     * @return
     */
    public boolean isTooken(HttpServletRequest request)
    {
    	try
    	{
    		String token = request.getHeader("token");
    		if(StringUtils.isNotEmpty(token))
    		{
    			return true;
    		}
    		else
    		{
    			return false;
    		}
    		
    	}
    	catch (Exception e) {
		 return false;
   	 	}
    }
    
    /**
                * 通过token返回用户信息
     * @param request
     * @return
     */
    public SysUser getUserByTooken(HttpServletRequest request)
   	{
    	SysUser fu=new SysUser();
    	try
    	{
	    	String scmsToken = request.getHeader("token");
	    	if(StringUtils.isBlank(scmsToken))
	    	{
	    		return null;	
	    	}
	    	String userId=redisUtils.get(scmsToken).toString();
	    	if(StringUtils.isBlank(scmsToken))
	    	{
	    		return null;	
	    	}
	    	fu= sysUserService.selectOne(userId);
	    	return fu;
    	}
    	catch (Exception e) {
		 return null;
   	 	}
   	}

}
